package com.example.sandbox;

import com.example.pojo.sandbox.ExecuteCodeRequest;
import com.example.pojo.sandbox.ExecuteCodeResponse;
import com.example.pojo.sandbox.ExecuteMessage;
import com.example.utils.FileUtils;
import com.example.utils.ResponseUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.List;

/**
 * @author ZhuYi
 * @create 2024/3/20 20:58
 */
@Component
@Slf4j
public class CCodeSandbox implements CodeSandbox {
    // 文件操作工具类
    @Autowired
    private FileUtils fileUtils;
    // 响应结果操作工具类
    @Autowired
    private ResponseUtils responseUtils;
    // java语言统一类名
    private static final String GLOBAL_C_CLASS_NAME = "Main.c";
    // 代码最长运行时间
    public static final long TIME_OUT = 10000L;

    // 实现java语言的编译执行
    @Override
    public ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest) {
        // 拿到待执行代码
        String code = executeCodeRequest.getCode();
        // 得到输入用例
        List<String> inputList = executeCodeRequest.getInputList();
        // 调用工具类将用户提交的代码保存为文件
        File userCodeFile = fileUtils.saveCodeToFile(code, GLOBAL_C_CLASS_NAME);
        // 获取代码文件路径
        String userCodeFilePath = userCodeFile.getAbsolutePath();
        int index = userCodeFilePath.lastIndexOf('.');
        String finalUserCodeFilePath = userCodeFilePath.substring(0, index);
        // 编译代码得到可运行文件,打印编译后信息
        String compileCmd = String.format("gcc %s -o %s", userCodeFilePath, finalUserCodeFilePath);
        ExecuteMessage compileFileExecuteMessage = fileUtils.compileCodeFile(compileCmd);
        log.info("编译后信息：" + compileFileExecuteMessage);
        // 获取代码文件父路径
        String userCodeFileParentPath = userCodeFile.getParentFile().getAbsolutePath();
        // 运行可执行文件获取执行后信息，打印可执行信息
        String runCmd = String.format(finalUserCodeFilePath);
        List<ExecuteMessage> runFileExecuteMessageList = fileUtils.runCodeFile(runCmd, inputList, TIME_OUT);
        log.info("运行后信息：" + runFileExecuteMessageList);
        ExecuteCodeResponse outputResponse = responseUtils.getOutputResponse(runFileExecuteMessageList);
        //文件清理
        boolean clearFile = fileUtils.clearFile(userCodeFile);
        if (!clearFile) {
            log.info("文件删除失败：" + userCodeFile.getAbsoluteFile());
        }
        return outputResponse;
    }
}
